
package com.trial.area.trade.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.IOUtils;
import com.trial.area.common.controller.BaseController;
import com.trial.area.common.param.SessionUserInfo;
import com.trial.area.config.ConfigUtils;
import com.trial.area.goods.entity.GoodsVO;
import com.trial.area.goods.service.GoodsService;
import com.trial.area.trade.entity.ChargeRecordVO;
import com.trial.area.trade.entity.TradeRecordVO;
import com.trial.area.trade.param.ChargeRecordParam;
import com.trial.area.trade.param.TradeRecordParam;
import com.trial.area.trade.service.ChargeRecordService;
import com.trial.area.trade.service.TradeRecordService;
import com.trial.area.weixin.common.WeixinUtils;

/**
 * 交易信息Controller
 *
 * @author 朱国军
 * @since 1.0
 * @version 2015年12月27日 朱国军
 */
@Controller
public class TradeH5Controller extends BaseController {
    
    private Logger logger = LoggerFactory.getLogger(TradeH5Controller.class);
    
    @Autowired
    private TradeRecordService tradeRecordService;

    @Autowired
    private ChargeRecordService chargeRecordService;
    
    @Autowired
    private GoodsService goodsService;
    
    private final static String LIST_PAGE = "/html5/trade/trade_list_ajax";
    
    private final static String VIEW_PAGE = "/html5/trade/trade_view";
    
    private final static String PAY_PROCESS_PAGE = "/html5/trade/pay_process";

    private final static String PAY_RESULT_PAGE = "/html5/trade/pay_result";

    @RequestMapping(value = "/check/trade/create", produces = "application/json;charset=utf-8;")
    @ResponseBody
    public String payCreate(TradeRecordVO tradeRecordVO) {
        SessionUserInfo seUser = (SessionUserInfo) session.getAttribute("sessionUserInfo");
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            String spbillCreateIp = IpKit.getRealIp(request);
            String openId = seUser.getUserInfo().getOpenId();
            resultMap = tradeRecordService.createTrade(tradeRecordVO, seUser.getUserId(), openId, getRealIp(spbillCreateIp), getPath());
            return JSONObject.toJSONString(resultMap);
        } catch (Exception e) {
            logger.error("创建交易信息出错", e);
            resultMap.put("result", false);
            resultMap.put("message", "创建交易信息出错：" + e.getLocalizedMessage());
            return JSONObject.toJSONString(resultMap);
        }
    }

    private String getRealIp(String spbillCreateIp) {
        if (StringUtils.contains(spbillCreateIp, ",")) {
            String[] ipList = StringUtils.split(spbillCreateIp, ",");
            if (ipList != null && ipList.length > 1) {
                return ipList[0];
            }
        }
        return spbillCreateIp;
    }
    
    @RequestMapping(value = "/check/trade/payprocess")
    public ModelAndView payProcess(String chargeId) {
        SessionUserInfo seUser = (SessionUserInfo) session.getAttribute("sessionUserInfo");
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            ChargeRecordVO chargeRecordVO = chargeRecordService.findById(chargeId);
            
            if (!StringUtils.equals(chargeRecordVO.getOpenId(), seUser.getUserInfo().getOpenId())) {
                resultMap.put("result", false);
                resultMap.put("message", "该订单属于另外一个帐号");
                return new ModelAndView(PAY_RESULT_PAGE, resultMap);
            }
            
            if (StringUtils.isBlank(chargeRecordVO.getPrepayId())) {
                resultMap.put("result", false);
                resultMap.put("message", "该订单未完成下单");
                return new ModelAndView(PAY_RESULT_PAGE, resultMap);
            }

            if (chargeRecordVO.getChargeState() != 2) {
                resultMap.put("result", false);
                resultMap.put("message", "该订单不可支付");
                return new ModelAndView(PAY_RESULT_PAGE, resultMap);
            }

            Map<String, String> orderResult = chargeRecordService.queryOrderStatus(chargeRecordVO.getTradeNo());
            if (StringUtils.equals("SUCCESS", orderResult.get("result"))) {
                return payResult(chargeId, null);
            } else if (!StringUtils.equals("NOTPAY", orderResult.get("result"))) {
                resultMap.put("result", false);
                resultMap.put("message", orderResult.get("message"));
                return new ModelAndView(PAY_RESULT_PAGE, resultMap);
            }

            Map<String, String> payJSDataMap = payJSData(chargeRecordVO.getPrepayId());
            resultMap.put("result", true);
            resultMap.put("message", "下单成功");
            resultMap.put("payJSDataMap", payJSDataMap);
            resultMap.put("chargeRecordVO", chargeRecordVO);
            return new ModelAndView(PAY_PROCESS_PAGE, resultMap);

        } catch (Exception e) {
            logger.error("新增或修改交易信息出错", e);
            resultMap.put("result", false);
            resultMap.put("message", "支付失败：" + e.getLocalizedMessage());
            return new ModelAndView(PAY_RESULT_PAGE, resultMap);
        }

    }
    
    private Map<String, String> payJSData(String prepayId) {
        Map<String, String> payJSDataMap = new HashMap<String, String>();
        // 公众号id appId 是 String(16) wx8888888888888888 商户注册具有支付权限的公众号成功后即可获得
        payJSDataMap.put("appId", WeixinUtils.getApiConfig().getAppId());
        // 时间戳 timeStamp 是 String(32) 1414561699 当前的时间，其他详见时间戳规则
        payJSDataMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        // 随机字符串 nonceStr 是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串，不长于32位。推荐随机数生成算法
        payJSDataMap.put("nonceStr", StringUtils.replace(UUID.randomUUID().toString(), "-", ""));
        // 订单详情扩展字符串 package 是 String(128) prepay_id=123456789 统一下单接口返回的prepay_id参数值，提交格式如：prepay_id=***
        payJSDataMap.put("package", "prepay_id=" + prepayId);
        // 签名方式 signType 是 String(32) MD5 签名算法，暂支持MD5
        payJSDataMap.put("signType", "MD5");
        // 签名 paySign 是 String(64) C380BEC2BFD727A4B6845133519F3AD6
        String paySign = PaymentKit.createSign(payJSDataMap, ConfigUtils.getStringValueByKey("weixin_paterner_key"));
        payJSDataMap.put("paySign", paySign);

        // 坑爹的微信，字段名叫package啊，JSP不能用这个变量啊，签完名把package换成packageString
        payJSDataMap.get("packageString");
        payJSDataMap.put("packageString", "prepay_id=" + prepayId);
        return payJSDataMap;
    }

    @RequestMapping(value = "/check/trade/pay")
    public ModelAndView payResult(String chargeId, String pagePayResult) {
        
        SessionUserInfo seUser = (SessionUserInfo) session.getAttribute("sessionUserInfo");
        
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            ChargeRecordVO chargeRecordVO = chargeRecordService.findById(chargeId);
            
            if (!StringUtils.equals(chargeRecordVO.getOpenId(), seUser.getUserInfo().getOpenId())) {
                resultMap.put("result", false);
                resultMap.put("message", "该订单属于另外一个帐号");
                return new ModelAndView(PAY_RESULT_PAGE, resultMap);
            }
            
            resultMap = payResultPrivate(chargeRecordVO, pagePayResult);
            
        } catch (Exception e) {
            logger.error("处理支付结果出错", e);
            resultMap.put("result", false);
            resultMap.put("message", "处理支付结果出错：" + e.getLocalizedMessage());
        }
        return new ModelAndView(PAY_RESULT_PAGE, resultMap);
    }
    
    private Map<String, Object> payResultPrivate(ChargeRecordVO chargeRecordVO, String pagePayResult) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        if (StringUtils.isBlank(chargeRecordVO.getPrepayId())) {
            resultMap.put("result", false);
            resultMap.put("message", "该订单未完成下单");
            return resultMap;
        }
        
        if (chargeRecordVO.getChargeState() == 3) {
            resultMap.put("result", true);
            resultMap.put("message", "运费支付成功");
            return resultMap;
        }
        
        if (chargeRecordVO.getChargeState() != 2) {
            resultMap.put("result", false);
            resultMap.put("message", "该订单不可支付");
            return resultMap;
        }

        Map<String, String> orderResult = chargeRecordService.updateOrderStatus(chargeRecordVO, pagePayResult);
        if (StringUtils.equals("SUCCESS", orderResult.get("result"))) {
            resultMap.put("result", true);
            resultMap.put("message", "运费支付成功");
        } else {
            resultMap.put("result", false);
            resultMap.put("message", orderResult.get("message"));
        }
        
        return resultMap;
    }

    @RequestMapping(value = "/uncheck/pay/notify")
    @ResponseBody
    public String payNotify() throws IOException {
        InputStream inStream = request.getInputStream();

        String requestString = IOUtils.toString(inStream);
        Map<String, String> orderResult = PaymentKit.xmlToMap(requestString);

        Map<String, String> result = new HashMap<String, String>();
        if (PaymentKit.verifyNotify(orderResult, ConfigUtils.getStringValueByKey("weixin_paterner_key"))) {
            String tradeNo = orderResult.get("out_trade_no");

            ChargeRecordParam chargeRecordParam = new ChargeRecordParam();
            chargeRecordParam.setTradeNo(tradeNo);
            List<ChargeRecordVO> chargeRecordList = chargeRecordService.queryByPage(chargeRecordParam);

            if (chargeRecordList != null && chargeRecordList.size() == 1) {
                payResultPrivate(chargeRecordList.get(0), null);
            } else {
                logger.error("微信支付回调通知出错，根据订单号：" + tradeNo + " 未找到支付记录");
            }
            result.put("return_code", "SUCCESS");
            result.put("return_msg", "OK");
        } else {
            result.put("return_code", "FAIL");
            result.put("return_msg", "签名验证不通过");
            logger.error("微信支付回调通知出错，签名验证不通过");
        }

        return PaymentKit.toXml(result);
    }

    @RequestMapping(value = "/check/trade/delete/{id}", produces = "application/json;charset=utf-8;")
    @ResponseBody
    public String delete(@PathVariable String id) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            Integer deleteCount = tradeRecordService.delete(id);
            if (deleteCount != null && deleteCount == 1) {
                resultMap.put("result", true);
                resultMap.put("message", "删除交易信息成功");
            } else {
                resultMap.put("result", false);
                resultMap.put("message", "删除交易信息失败");
            }
        } catch (Exception e) {
            logger.error("删除交易信息出错", e);
            resultMap.put("result", false);
            resultMap.put("message", "删除交易信息出错：" + e.getLocalizedMessage());
        }
        return JSONObject.toJSONString(resultMap);
    }
    
    @RequestMapping(value = "/check/trade/list")
    public ModelAndView queryList(TradeRecordParam tradeRecordParam) {
        SessionUserInfo seUser = (SessionUserInfo) session.getAttribute("sessionUserInfo");
        Map<String, Object> resultMap = new HashMap<String, Object>();
        
        tradeRecordParam.setUserId(seUser.getUserId());
        
        List<Map<String, Object>> dataList = tradeRecordService.queryByPage(tradeRecordParam);
        resultMap.put("dataList", dataList);
        resultMap.put("paramMap", tradeRecordParam);
        return new ModelAndView(LIST_PAGE, resultMap);
    }

    @RequestMapping(value = "/check/trade/view/{id}")
    public ModelAndView viewTradeInfo(@PathVariable String id) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        TradeRecordVO tradeRecordVO = tradeRecordService.findById(id);
        resultMap.put("tradeRecordVO", tradeRecordVO);
        
        GoodsVO goodsVO = goodsService.findById(tradeRecordVO.getGoodsId());
        if (StringUtils.isNotBlank(goodsVO.getGoodsProperties())) {
            String[] properties = StringUtils.split(goodsVO.getGoodsProperties(), ":");
            String propertiesName = properties[0];
            resultMap.put("propertiesName", propertiesName);
        }
        resultMap.put("goodsVO", goodsVO);

        ChargeRecordVO chargeRecordVO = chargeRecordService.findByTradeId(tradeRecordVO.getTradeId());
        resultMap.put("chargeRecordVO", chargeRecordVO);
        return new ModelAndView(VIEW_PAGE, resultMap);
    }
}
